//
//  Authorize.swift
//  ADKit
//
//  Created by Adoma on 2020/10/22.
//

import UIKit
import CoreLocation
import AVFoundation
import Photos
import Contacts
import UserNotifications

/// by ADKit
public class Authorize: NSObject {
    
    public enum AuthorizeType: Int {
        
        case notification
        case location
        case camera
        case photoLibrary
        case microPhone
        case contacts

    }
    
    public enum AuthorizeStatus: Int {
        case notDetermined
        case authorized
        case denied
    }
    
    public static var shared = Authorize()
    
    lazy var locationManger = CLLocationManager.init()
    lazy var contactStore = CNContactStore.init()
    lazy var notificationCenter = UNUserNotificationCenter.current()
    var complete: Complete?

    public typealias Complete = (AuthorizeStatus)->Void
    
    public func getAuthorize(type: AuthorizeType, complete: @escaping Complete) {
        switch type {
        case .notification:
            notificationCenter.getNotificationSettings { setting in
                switch setting.authorizationStatus {
                case .notDetermined:
                    complete(.notDetermined)
                case .authorized:
                    complete(.authorized)
                default:
                    complete(.denied)
                }
            }
        case .contacts:
            let auth = CNContactStore.authorizationStatus(for: .contacts)
            switch auth {
            case .notDetermined:
                complete(.notDetermined)
            case .authorized:
                complete(.authorized)
            default:
                complete(.denied)
            }
        case .location:
            let auth = CLLocationManager.authorizationStatus()
            switch auth {
            case .notDetermined:
                complete(.notDetermined)
            case .authorized:
                complete(.authorized)
            default:
                complete(.denied)
            }
        case .camera:
            let auth = AVCaptureDevice.authorizationStatus(for: .video)
            switch auth {
            case .notDetermined:
                complete(.notDetermined)
            case .authorized:
                complete(.authorized)
            default:
                complete(.denied)
            }
        case .photoLibrary:
            let auth = PHPhotoLibrary.authorizationStatus()
            switch auth {
            case .notDetermined:
                complete(.notDetermined)
            case .authorized:
                complete(.authorized)
            default:
                complete(.denied)
            }
        case .microPhone:
            let auth = AVCaptureDevice.authorizationStatus(for: .audio)
            switch auth {
            case .notDetermined:
                complete(.notDetermined)
            case .authorized:
                complete(.authorized)
            default:
                complete(.denied)
            }
        }
    }
    
    public func authorize(type: AuthorizeType, complete: @escaping Complete) {
     
        switch type {
        case .notification:
            checkNotificationAuth(complete: complete)
        case .contacts:
            checkContactsAuth(complete: complete)
        case .location:
            checkLocationAuth(complete: complete)
        case .camera:
            checkCameraAuth(complete: complete)
        case .photoLibrary:
            checkPhotoLibraryAuth(complete: complete)
        case .microPhone:
            checkMicroPhoneAuth(complete: complete)
        }
    }
    
    func checkNotificationAuth(complete: @escaping Complete) {
        getAuthorize(type: .notification) { status in
            switch status {
            case .notDetermined:
                self.notificationCenter.requestAuthorization(options: [.badge, .sound, .alert]) { granted, _ in
                    if granted {
                        complete(.authorized)
                    } else {
                        complete(.denied)
                    }
                }
            default:
                complete(status)
            }
        }
    }
    
    func checkContactsAuth(complete: @escaping Complete) {
        
        getAuthorize(type: .contacts) { status in
            switch status {
            case .notDetermined:
                self.contactStore.requestAccess(for: .contacts) { (success, _) in
                    if success {
                        complete(.authorized)
                    } else {
                        complete(.denied)
                    }
                }
            default:
                complete(status)
            }
        }
    }
    
    func checkLocationAuth(complete: @escaping Complete) {
        
        getAuthorize(type: .location) { status in
            switch status {
            case .notDetermined:
                self.complete = complete
                self.locationManger.delegate = self
                self.locationManger.requestWhenInUseAuthorization()
            default:
                complete(status)
            }
        }

    }
    
    func checkCameraAuth(complete: @escaping Complete) {
        
        getAuthorize(type: .camera) { status in
            switch status {
            case .notDetermined:
                AVCaptureDevice.requestAccess(for: .video) { success in
                    if success {
                        complete(.authorized)
                    } else {
                        complete(.denied)
                    }
                }
            default:
                complete(status)
            }
        }

    }
    
    func checkPhotoLibraryAuth(complete: @escaping Complete) {
        
        getAuthorize(type: .photoLibrary) { status in
            switch status {
            case .notDetermined:
                PHPhotoLibrary.requestAuthorization { status in
                    switch status {
                    case .authorized:
                        complete(.authorized)
                    default:
                        complete(.denied)
                    }
                }
            default:
                complete(status)
            }
        }

    }
    
    func checkMicroPhoneAuth(complete: @escaping Complete) {
        
        getAuthorize(type: .microPhone) { status in
            switch status {
            case .notDetermined:
                AVCaptureDevice.requestAccess(for: .audio) { success in
                    if success {
                        complete(.authorized)
                    } else {
                        complete(.denied)
                    }
                }
            default:
                complete(status)
            }
        }

    }
   
}

extension Authorize: CLLocationManagerDelegate {
    
    public func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        switch status {
        case .authorizedWhenInUse, .authorizedAlways:
            complete?(.authorized)
        default:
            complete?(.denied)
        }
    }
}
